﻿using System.Collections.Generic;
using System.Collections.ObjectModel;
using CodePlex.DnD4eCampaignManager.DnD4e;
using CodePlex.DnD4eCampaignManager.Presentation;
using CodePlex.DnD4eCampaignManager.Presentation.ViewInterfaces;
using CodePlex.DnD4eCampaignManager.Repositories.Interfaces;
using NUnit.Framework;
using Rhino.Mocks;

namespace CodePlex.DnD4eCampaignManager.CampaignManagerTests.PresentationTests
{
    [TestFixture]
    public class LocationPresenterTests
    {
        private const string LOCATION_DESCRIPTION = "There is a waterfall and some nice trees";
        private const string LOCATION_DISTANCES = "Here is a distance";
        private const string LOCATION_NAME = "Some place nice";
        private const string LOCATION_NPCS = "A fairy watches over the pond";
        private Location _location;
        private MockRepository Mocks { get; set; }

        [Test]
        public void DisplayLocationLoadedFromTheRepository()
        {
            ILocationView locationView = Mocks.StrictMock<ILocationView>();
            ILocationRepository locationRepository = Mocks.StrictMock<ILocationRepository>();
            LocationPresenter presenter = new LocationPresenter(LOCATION_NAME, locationView, locationRepository);
            using ( Mocks.Record() )
            {
                LoadAndDisplayLocation(locationView, locationRepository);
            }
            using ( Mocks.Playback() )
            {
                presenter.DisplayLocation();
            }
        }

        [Test]
        public void SaveLocationSendsTheLocationDataToTheRepository()
        {
            ILocationView locationView = Mocks.StrictMock<ILocationView>();
            ILocationRepository locationRepository = Mocks.StrictMock<ILocationRepository>();
            LocationPresenter presenter = new LocationPresenter(LOCATION_NAME, locationView, locationRepository);
            using ( Mocks.Record() )
            {
                RetrieveLocationFromViewAndSave(locationView, locationRepository);
            }
            using ( Mocks.Playback() )
            {
                presenter.SaveLocation();
            }
        }

        [SetUp]
        public void SetUp()
        {
            Mocks = new MockRepository();
        }

        private void LoadAndDisplayLocation(ILocationView view, ILocationRepository repository)
        {
            TestLocation();
            ReadOnlyCollection<string> locationNames = new ReadOnlyCollection<string>(new List<string> { LOCATION_NAME });
            Expect.Call(repository.GetAllNames()).Return(locationNames);
            Expect.Call(repository.GetByName(LOCATION_NAME)).Return(_location);
            view.LocationName = LOCATION_NAME;
            view.LocationDescription = LOCATION_DESCRIPTION;
            view.LocationNPCs = LOCATION_NPCS;
            view.LocationDistances = LOCATION_DISTANCES;
        }

        private void RetrieveLocationFromViewAndSave(ILocationView view, ILocationRepository repository)
        {
            TestLocation();
            Expect.Call(view.LocationDescription).Return(LOCATION_DESCRIPTION);
            Expect.Call(view.LocationDistances).Return(LOCATION_DISTANCES);
            Expect.Call(view.LocationNPCs).Return(LOCATION_NPCS);
            repository.Save(_location);
        }

        private void TestLocation()
        {
            _location = new Location
                            {
                                Name = LOCATION_NAME,
                                Description = LOCATION_DESCRIPTION,
                                Npcs = LOCATION_NPCS,
                                Distances = LOCATION_DISTANCES
                            };
        }
    }
}